home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / src / gui.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  56.5 KB  |  1,978 lines

  1. // MDF - PORT FROM NCSA VERSION 2.1
  2. // In progress.
  3.  
  4. /****************************************************************************
  5.  * NCSA Mosaic for the X Window System                        *
  6.  * Software Development Group                            *
  7.  * National Center for Supercomputing Applications                *
  8.  * University of Illinois at Urbana-Champaign                    *
  9.  * 605 E. Springfield, Champaign IL 61820                    *
  10.  * mosaic@ncsa.uiuc.edu                             *
  11.  *                                        *
  12.  * Copyright (C) 1993, Board of Trustees of the University of Illinois        *
  13.  *                                        *
  14.  * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
  15.  * copyrighted by The Board of Trustees of the University of Illinois        *
  16.  * (UI), and ownership remains with the UI.                    *
  17.  *                                        *
  18.  * The UI grants you (hereafter, Licensee) a license to use the Software    *
  19.  * for academic, research and internal business purposes only, without a    *
  20.  * fee.  Licensee may distribute the binary and source code (if released)   *
  21.  * to third parties provided that the copyright notice and this statement   *
  22.  * appears on all copies and that no charge is associated with such        *
  23.  * copies.                                    *
  24.  *                                        *
  25.  * Licensee may make derivative works.    However, if Licensee distributes    *
  26.  * any derivative work based on or derived from the Software, then        *
  27.  * Licensee will (1) notify NCSA regarding its distribution of the        *
  28.  * derivative work, and (2) clearly notify users that such derivative        *
  29.  * work is a modified version and not the original NCSA Mosaic            *
  30.  * distributed by the UI.                            *
  31.  *                                        *
  32.  * Any Licensee wishing to make commercial use of the Software should        *
  33.  * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
  34.  * commercial use.  Commercial use includes (1) integration of all or        *
  35.  * part of the source code into a product for sale or license by or on        *
  36.  * behalf of Licensee to third parties, or (2) distribution of the binary   *
  37.  * code or source code to third parties that need it to utilize a        *
  38.  * commercial product sold or licensed by or on behalf of Licensee.        *
  39.  *                                        *
  40.  * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
  41.  * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
  42.  * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
  43.  * USERS OF THIS SOFTWARE.                            *
  44.  *                                        *
  45.  * By using or copying this Software, Licensee agrees to abide by the        *
  46.  * copyright law and all other applicable laws of the U.S. including, but   *
  47.  * not limited to, export control laws, and the terms of this license.        *
  48.  * UI shall have the right to terminate this license immediately by        *
  49.  * written notice upon Licensee's breach of, or non-compliance with, any    *
  50.  * of its terms.  Licensee may be held legally responsible for any        *
  51.  * copyright infringement that is caused or encouraged by Licensee's        *
  52.  * failure to abide by the terms of this license.                *
  53.  *                                        *
  54.  * Comments and questions are welcome and can be sent to            *
  55.  * mosaic-x@ncsa.uiuc.edu.                            *
  56.  ****************************************************************************/
  57.  
  58. #include "includes.h"
  59. #include "HTML.h"
  60. #include "mosaic.h"
  61. #include "globals.h"
  62.  
  63. #include <signal.h>
  64. #include <sys/types.h>
  65.  
  66. /* don't think we need these - MDF 1/12/94
  67. #include <sys/socket.h>
  68. #include <netinet/in.h>
  69. #include <netdb.h>
  70. */
  71.  
  72. #include "XtoI.h"
  73. //#include "spinner.h"
  74. #include "BoingTransfer.h"
  75.  
  76. /*
  77.  * Globals used by the pixmaps for the animated icon.
  78.  * Marc, I imagine you might want to do something cleaner
  79.  * with these?
  80.  */
  81. extern Pixmap IconPix[NUMBER_OF_FRAMES];
  82. extern int IconsMade;
  83.  
  84. /* ------------------------------ variables ------------------------------- */
  85.  
  86. Widget toplevel;
  87. Widget view = NULL;  /* HORRIBLE HACK @@@@ */
  88. int Vclass;  /* visual class for 24bit support hack */
  89. AppData Rdata;    /* extern'd in mosaic.h */
  90. char *global_xterm_str;  /* required for HTAccess.c now */
  91.  
  92. char *uncompress_program="gunzip";
  93. char *gunzip_program="gunzip";
  94.  
  95. int use_default_extension_map = 1;
  96. char *global_extension_map   ="env:mosaic/mime.types";
  97. char *personal_extension_map ="env:mosaic/personal_mime.types";
  98. int use_default_type_map = 1;
  99. char *global_type_map         ="env:mosaic/mailcap";
  100. char *personal_type_map      ="env:mosaic/personal_mailcap";
  101.  
  102. int tweak_gopher_types;
  103. int max_wais_responses;
  104. int have_hdf = 0;
  105. int twirl_increment;
  106.  
  107. /* This is exported to libwww, like altogether too many other
  108.    variables here. */
  109. int binary_transfer;
  110. /* Now we cache the current window right before doing a binary
  111.    transfer, too.  Sheesh, this is not pretty. */
  112. mo_window *current_win;
  113.  
  114. /* If startup_document is set to anything but NULL, it will be the
  115.    initial document viewed (this is separate from home_document
  116.    below). */
  117. char *startup_document = NULL;
  118. /* If startup_document is NULL home_document will be the initial
  119.    document. */
  120. char *home_document = NULL;
  121. char *machine;
  122. char *shortmachine;
  123. char *machine_with_domain;
  124.  
  125. XColor fg_color, bg_color;
  126.  
  127. static void *busy_cursor;
  128. static int busy = 0;
  129. static Widget *busylist = NULL;
  130. char *cached_url = NULL;
  131.  
  132. /* Forward declaration of test predicate. */
  133. int anchor_visited_predicate (Widget, char *);
  134.  
  135. /* When we first start the application, we call mo_startup()
  136.    after creating the unmapped toplevel widget.  mo_startup()
  137.    either sets the value of this to 1 or 0.  If 0, we don't
  138.    open a starting window. */
  139. int defer_initial_window;
  140.  
  141. extern char *HTDescribeURL (char *);
  142. extern mo_status mo_post_access_document (mo_window *win, char *url,
  143.                       char *content_type,
  144.                       char *post_data);
  145.  
  146. /* ----------------------------- WINDOW LIST ------------------------------ */
  147. /* Amiga Mosaic doesn't support multiple windows yet, so this is empty.     */
  148. /* ----------------------------- WINDOW LIST ------------------------------ */
  149.  
  150.  
  151. /****************************************************************************
  152.  * name:    mo_assemble_help_url
  153.  * purpose: Make a temporary, unique filename.
  154.  * inputs:
  155.  *   - char *file: Filename to be appended to Rdata.docs_directory.
  156.  * returns:
  157.  *   The desired help url (a malloc'd string).
  158.  * remarks:
  159.  ****************************************************************************/
  160. char *mo_assemble_help_url (char *file)
  161. {
  162.   char *tmp;
  163.  
  164.   if (!file)
  165.     return strdup ("http://lose.lose/lose");
  166.  
  167.   tmp = (char *)malloc ((strlen (file) + strlen (Rdata.docs_directory) + 4) *
  168.             sizeof (char));
  169.  
  170.   if (Rdata.docs_directory[strlen(Rdata.docs_directory)-1] == '/')
  171.     {
  172.       /* Trailing slash in docs_directory spec. */
  173.       sprintf (tmp, "%s%s", Rdata.docs_directory, file);
  174.     }
  175.   else
  176.     {
  177.       /* No trailing slash. */
  178.       sprintf (tmp, "%s/%s", Rdata.docs_directory, file);
  179.     }
  180.  
  181.   return tmp;
  182. }
  183.  
  184.  
  185. /* ----------------------------- busy cursor ------------------------------ */
  186.  
  187. mo_status mo_not_busy (void)
  188. {
  189.   if (busy)
  190.     {
  191. //    set(App, MUIA_Application_Sleep, FALSE);
  192.       busy = 0;
  193.     }
  194.   return mo_succeed;
  195. }
  196.  
  197. mo_status mo_busy (void)
  198. {
  199.   if (!busy)
  200.     {
  201. //    set(App, MUIA_Application_Sleep, TRUE);
  202.       busy = 1;
  203.     }
  204.   return mo_succeed;
  205. }
  206.  
  207.  
  208. /****************************************************************************
  209.  * name:    mo_redisplay_window
  210.  * purpose: Cause the current window's HTML widget to be refreshed.
  211.  *        This causes the anchors to be reexamined for visited status.
  212.  * inputs:
  213.  *   - mo_window *win: Current window.
  214.  * returns:
  215.  *   mo_succeed
  216.  * remarks:
  217.  *
  218.  ****************************************************************************/
  219. mo_status mo_redisplay_window (mo_window *win)
  220. {
  221.   struct Gadget *g;
  222.   struct Window *w;
  223.   char *curl = cached_url;
  224.   cached_url = win->cached_url;
  225.  
  226. //  HTMLRetestAnchors (win->scrolled_win, anchor_visited_predicate);
  227.   cached_url = curl;
  228.  
  229. /* AUTO NOW?
  230.   GetAttr(MUIA_Boopsi_Object, HTML_gad, (ULONG *)(&g));
  231.   GetAttr(MUIA_Window_Window, WI_Main, (ULONG *)(&w));
  232.   RefreshGList(g, w, NULL, 1);
  233. */
  234.   return mo_succeed;
  235. }
  236.  
  237.  
  238. /* ---------------------- mo_set_current_cached_win ----------------------- */
  239.  
  240. mo_status mo_set_current_cached_win (mo_window *win)
  241. {
  242.   current_win = win;
  243.   view = win->view;
  244.  
  245.   return mo_succeed;
  246. }
  247.  
  248. static short connect_interrupt = 0; /* 2 Bytes */
  249. short image_interrupt = 0;   /* +2 Bytes = 1 Longword */
  250. void icon_pressed_cb(void)
  251. {
  252.   connect_interrupt = 1;
  253. }
  254.  
  255. #ifndef _AMIGA
  256. /****************************************************************************
  257.  * name:    anchor_cb
  258.  * purpose: Callback for triggering anchor in HTML widget.
  259.  * inputs:
  260.  *   - as per XmxCallback
  261.  * returns:
  262.  *   nothing
  263.  * remarks:
  264.  *   This is too complex and should be broken down.
  265.  *   We look at the button event passed in through the callback;
  266.  *   button1 == same window, button2 == new window.
  267.  *   Call mo_open_another_window or mo_load_window_text to get
  268.  *   the actual work done.
  269.  ****************************************************************************/
  270. static XmxCallback (anchor_cb)
  271. {
  272.   char *href, *reftext;
  273.   char *access;
  274.   mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
  275.   XButtonReleasedEvent *event =
  276.     (XButtonReleasedEvent *)(((WbAnchorCallbackData *)call_data)->event);
  277.   int force_newwin = (event->button == Button2 ? 1 : 0);
  278.  
  279.   if (!win)
  280.     return;
  281.  
  282.   if (Rdata.protect_me_from_myself)
  283.     {
  284.       int answer = XmxModalYesOrNo
  285.     (win->base, app_context,
  286.      "BEWARE: Despite our best and most strenuous intentions to the contrary,\nabsolutely anything could be on the other end of this hyperlink,\nincluding -- quite possibly -- pornography, or even nudity.\n\nNCSA disclaims all responsibility regardi
  287. g your emotional and mental health\nand specifically all responsibility for effects of viewing salacious material via Mosaic.\n\nWith that in mind, are you *sure* you want to follow this hyperlink???",
  288.      "Yup, I'm sure, really.", "Ack, no!  Get me outta here.");
  289.       if (!answer)
  290.     return;
  291.     }
  292.  
  293.   if (((WbAnchorCallbackData *)call_data)->href)
  294.     href = strdup (((WbAnchorCallbackData *)call_data)->href);
  295.   else
  296.     href = strdup ("Unlinked");
  297.   if (((WbAnchorCallbackData *)call_data)->text)
  298.     reftext = strdup (((WbAnchorCallbackData *)call_data)->text);
  299.   else
  300.     reftext = strdup ("Untitled");
  301.  
  302.   mo_convert_newlines_to_spaces (href);
  303.  
  304.   if (!force_newwin)
  305.     mo_load_window_text (win, href, reftext);
  306.   else
  307.     {
  308.       char *target = mo_url_extract_anchor (href);
  309.       char *url =
  310.     mo_url_canonicalize_keep_anchor (href, win->current_node->url);
  311.       /* @@@ should we be keeping the anchor here??? */
  312.       if (strncmp (url, "telnet:", 7) && strncmp (url, "tn3270:", 7) &&
  313.       strncmp (url, "rlogin:", 7))
  314.     {
  315.       /* Not a telnet anchor. */
  316.  
  317.       /* Open the window (generating a new cached_url). */
  318.       mo_open_another_window (win, url, reftext, target);
  319.  
  320.       /* Now redisplay this window. */
  321.       mo_redisplay_window (win);
  322.     }
  323.       else
  324.     /* Just do mo_load_window_text go get the xterm forked off. */
  325.     mo_load_window_text (win, url, reftext);
  326.     }
  327.  
  328.   free (href);
  329.   return;
  330. }
  331. #endif
  332.  
  333.  
  334. /****************************************************************************
  335.  * name:    anchor_visited_predicate (PRIVATE)
  336.  * purpose: Called by the HTML widget to determine whether a given URL
  337.  *        has been previously visited.
  338.  * inputs:
  339.  *   - Widget    w: HTML widget that called this routine.
  340.  *   - char *href: URL to test.
  341.  * returns:
  342.  *   1 if href has been visited previously; 0 otherwise.
  343.  * remarks:
  344.  *   All this does is canonicalize the URL and call
  345.  *   mo_been_here_before_huh_dad() to figure out if we've been
  346.  *   there before.
  347.  ****************************************************************************/
  348. int anchor_visited_predicate (Widget w, char *href)
  349. {
  350.   int rv;
  351.  
  352.   if (!Rdata.track_visited_anchors || !href)
  353.     return 0;
  354.  
  355.   /* This doesn't do special things for data elements inside
  356.      an HDF file, because it's faster this way. */
  357.   href = mo_url_canonicalize (href, cached_url);
  358.  
  359.   rv = (mo_been_here_before_huh_dad (href) == mo_succeed ? 1 : 0);
  360.  
  361.   free (href);
  362.   return rv;
  363. }
  364.  
  365. #ifndef _AMIGA
  366. static void pointer_motion_callback (Widget w, char *href)
  367. {
  368.   mo_window *win = NULL;
  369.   XmString xmstr;
  370.   char *to_free = NULL, *to_free_2 = NULL;
  371.  
  372.   if (!Rdata.track_pointer_motion)
  373.     return;
  374.  
  375.   while (win = mo_next_window (win))
  376.     if (win->scrolled_win == w)
  377.       goto foundit;
  378.  
  379.   /* Shit outta luck. */
  380.   return;
  381.  
  382.  foundit:
  383.  
  384.   if (href && *href)
  385.     {
  386.       href = mo_url_canonicalize_keep_anchor (href, win->cached_url);
  387.       to_free = href;
  388.  
  389.       /* Sigh... */
  390.       mo_convert_newlines_to_spaces (href);
  391.  
  392.       /* This is now the option wherein the URLs are just spit up there;
  393.      else we put up something more friendly. */
  394.       if (Rdata.track_full_url_names)
  395.     {
  396.       /* Everything already done... */
  397.     }
  398.       else
  399.     {
  400.       /* This is where we go get a good description. */
  401.       href = HTDescribeURL (href);
  402.       to_free_2 = href;
  403.     }
  404.     }
  405.   else
  406.     href = " ";
  407.   xmstr = XmStringCreateLtoR (href, XmSTRING_DEFAULT_CHARSET);
  408.   XtVaSetValues
  409.     (win->tracker_label,
  410.      XmNlabelString, (XtArgVal)xmstr,
  411.      NULL);
  412.   XmStringFree (xmstr);
  413.  
  414.   if (to_free)
  415.     free (to_free);
  416.   if (to_free_2)
  417.     free (to_free_2);
  418.  
  419.   return;
  420. }
  421. #endif
  422.  
  423.  
  424. #ifndef _AMIGA
  425. XmxCallback (submit_form_callback)
  426. {
  427.   mo_window *win = NULL;
  428.   char *url = NULL, *method = NULL, *enctype = NULL, *query;
  429.   int len, i;
  430.   WbFormCallbackData *cbdata = (WbFormCallbackData *)call_data;
  431.   int do_post_urlencoded = 0;
  432.  
  433.   if (!cbdata)
  434.     return;
  435.  
  436.   while (win = mo_next_window (win))
  437.     if (win->scrolled_win == w)
  438.       goto foundit;
  439.  
  440.   /* Shit outta luck. */
  441.   return;
  442.  
  443.  foundit:
  444.  
  445.   mo_busy ();
  446.  
  447.   /* Initial query: Breathing space. */
  448.   len = 16;
  449.  
  450.   /* Add up lengths of strings. */
  451.   for (i = 0; i < cbdata->attribute_count; i++)
  452.     {
  453.       if (cbdata->attribute_names[i])
  454.     {
  455.       len += strlen (cbdata->attribute_names[i]) * 3;
  456.       if (cbdata->attribute_values[i])
  457.         len += strlen (cbdata->attribute_values[i]) * 3;
  458.     }
  459.       len += 2;
  460.     }
  461.  
  462.   /* Get the URL. */
  463.   if (cbdata->href && *(cbdata->href))
  464.     url = cbdata->href;
  465.   else
  466.     url = win->current_node->url;
  467.  
  468.   if (cbdata->method && *(cbdata->method))
  469.     method = cbdata->method;
  470.   else
  471.     method = strdup ("GET");
  472.  
  473.   /* Grab enctype if it's there. */
  474.   if (cbdata->enctype && *(cbdata->enctype))
  475.     enctype = cbdata->enctype;
  476.  
  477. #if 0
  478.   fprintf (stderr, "[submit_form_callback] method is '%s'\n",
  479.        method);
  480.   fprintf (stderr, "[submit_form_callback] enctype is '%s'\n",
  481.        enctype);
  482. #endif
  483.  
  484.   if (strcmp (method, "POST") == 0)
  485.     do_post_urlencoded = 1;
  486.  
  487.   len += strlen (url);
  488.  
  489.   query = (char *)malloc (sizeof (char) * len);
  490.  
  491.   if (!do_post_urlencoded)
  492.     {
  493.       strcpy (query, url);
  494.       /* Clip out anchor. */
  495.       strtok (query, "#");
  496.       /* Clip out old query. */
  497.       strtok (query, "?");
  498.       if (query[strlen(query)-1] != '?')
  499.     {
  500.       strcat (query, "?");
  501.     }
  502.     }
  503.   else
  504.     {
  505.       /* Get ready for cats below. */
  506.       query[0] = 0;
  507.     }
  508.  
  509.   /* Take isindex possibility into account. */
  510.   if (cbdata->attribute_count == 1 &&
  511.       strcmp (cbdata->attribute_names[0], "isindex") == 0)
  512.     {
  513.       if (cbdata->attribute_values[0])
  514.     {
  515.       char *c = mo_escape_part (cbdata->attribute_values[0]);
  516.       strcat (query, c);
  517.       free (c);
  518.     }
  519.     }
  520.   else
  521.     {
  522.       for (i = 0; i < cbdata->attribute_count; i++)
  523.     {
  524.       /* For all but the first, lead off with an ampersand. */
  525.       if (i != 0)
  526.         strcat (query, "&");
  527.       /* Rack 'em up. */
  528.       if (cbdata->attribute_names[i])
  529.         {
  530.           char *c = mo_escape_part (cbdata->attribute_names[i]);
  531.           strcat (query, c);
  532.           free (c);
  533.  
  534.           strcat (query, "=");
  535.  
  536.           if (cbdata->attribute_values[i])
  537.         {
  538.           char *c = mo_escape_part (cbdata->attribute_values[i]);
  539.           strcat (query, c);
  540.           free (c);
  541.         }
  542.         }
  543.     }
  544.     }
  545.  
  546.   if (do_post_urlencoded)
  547.     {
  548.       mo_post_access_document (win, url, "application/x-www-form-urlencoded",
  549.                    query);
  550.     }
  551.   else
  552.     {
  553.       mo_access_document (win, query);
  554.     }
  555.  
  556.   free (query);
  557.  
  558.   return;
  559. }
  560. #endif
  561.  
  562.  
  563. #ifndef _AMIGA
  564. /* This only gets called by the widget in the middle of set_text. */
  565. static XmxCallback (link_callback)
  566. {
  567.   mo_window *win = current_win;
  568.   LinkInfo *linfo = (LinkInfo *)call_data;
  569.   extern char *url_base_override;
  570.  
  571.   if (!linfo)
  572.     return;
  573.  
  574.   /* Free -nothing- in linfo. */
  575.   if (linfo->href)
  576.     {
  577.       url_base_override = strdup (linfo->href);
  578.  
  579.       /* Set the URL cache variables to the correct values NOW. */
  580.       cached_url = mo_url_canonicalize (url_base_override, "");
  581.       win->cached_url = cached_url;
  582.     }
  583.   if (linfo->role)
  584.     {
  585.       /* Do nothing with the role crap yet. */
  586.     }
  587.  
  588.   return;
  589. }
  590. #endif
  591.  
  592.  
  593. /* Exported to libwww2. */
  594. void mo_gui_notify_progress(char *msg)
  595. {
  596. //  mo_window *win = current_win;
  597.   char word3[100];
  598.   static char sz[15];
  599.   int page, x, y;
  600.  
  601. //  if (!Rdata.track_pointer_motion)
  602. //    return;
  603.  
  604.   if (!msg)
  605.     msg = " ";
  606.  
  607.   sscanf(msg, "%*s %d %s %d", &x, word3, &y);
  608.   if (!strncmp(word3, "of", 2)) { /* Read X of Y bytes? */
  609.     get(PG_Bottom, MUIA_Group_ActivePage, &page);
  610.     if (page != 1) {
  611.       set(PG_Bottom, MUIA_Group_ActivePage, 1);
  612.     }
  613.     set(GG_Progress, MUIA_Gauge_Current, (100 * x / y));
  614.     sprintf(sz, "%d", y);
  615.     set(TX_Progress, MUIA_Text_Contents, sz);
  616.   } else {            /* Normal message */
  617.     get(PG_Bottom, MUIA_Group_ActivePage, &page);
  618.     if (page != 0) {
  619.       set(PG_Bottom, MUIA_Group_ActivePage, 0);
  620.     }
  621.     set(TX_Dest, MUIA_Text_Contents, msg);
  622.   }
  623.  
  624.   return;
  625. }
  626.  
  627. void UpdateButtons (Widget w)
  628. {
  629.   /* MDF - I don't think we need this function */
  630. }
  631.  
  632.  
  633. static int logo_count = 0;
  634.  
  635. int mo_gui_check_icon (int twirl)
  636. {
  637. //  mo_window *win = current_win;
  638.   int ret;
  639.  
  640. //if (twirl && Rdata.twirling_transfer_icon)
  641. //    {
  642. //    logo_count++;
  643. //    if (logo_count == 8) {
  644. //    logo_count = 0;
  645. //    }
  646. //    set(BT_Interrupt, SPIN_state, logo_count);
  647. //    }
  648.     /* Move the boing ball */
  649.     DoMethod(BT_Interrupt,MUIM_BoingTransfer_Move);
  650.  
  651.   /* Have MUI check for any user input (i.e. buttons..) */
  652.   DoMethod(App, MUIM_Application_InputBuffered);
  653.  
  654.   ret = connect_interrupt;
  655.   image_interrupt = connect_interrupt;
  656.   connect_interrupt = 0;
  657.  
  658.   return(ret);
  659. }
  660.  
  661.  
  662. void mo_gui_clear_icon (void)
  663. {
  664.   connect_interrupt = 0;
  665. //  set(BT_Interrupt, MUIA_Image_State, IDS_NORMAL);
  666. }
  667.  
  668. void mo_gui_done_with_icon (void)
  669. {
  670. //  mo_window *win = current_win;
  671.  
  672.   if (Rdata.larry_bitmaps)
  673.     {
  674. //    XmxApplyPixmapToLabelWidget
  675. //      (win->logo, xmosaic_up_pix);
  676.     }
  677.   else
  678.     {
  679. //    XClearArea(XtDisplay(win->logo), XtWindow(win->logo), 0, 0, 0, 0, True);
  680.     }
  681.  
  682. //  set(BT_Interrupt, MUIA_Image_State, IDS_NORMAL);
  683.   logo_count = 0;
  684. }
  685.  
  686.  
  687. void mo_view_keypress_handler(void)
  688. {
  689.   /* MDF - I don't think we need this */
  690. }
  691.  
  692.  
  693. #ifndef _AMIGA
  694. /****************************************************************************
  695.  * name:    mo_fill_window (PRIVATE)
  696.  * purpose: Take a new (empty) mo_window struct and fill in all the
  697.  *        GUI elements.
  698.  * inputs:
  699.  *   - mo_window *win: The window.
  700.  * returns:
  701.  *   mo_succeed
  702.  * remarks:
  703.  *
  704.  ****************************************************************************/
  705. static mo_status mo_fill_window (mo_window *win)
  706. {
  707.   Widget form;
  708.   Widget frame, rc;
  709.   Widget title_label, url_label;
  710.  
  711.   form = XmxMakeForm (win->base);
  712.  
  713.   /* Create the menubar. */
  714.   win->menubar = mo_make_document_view_menubar (form);
  715.  
  716.   XmxRSetToggleState (win->menubar, win->font_size, XmxSet);
  717.  
  718.   win->binary_transfer = 0;
  719.   XmxRSetToggleState (win->menubar, mo_binary_transfer,
  720.               (win->binary_transfer ? XmxSet : XmxNotSet));
  721.   win->delay_image_loads = Rdata.delay_image_loads;
  722.   XmxRSetToggleState (win->menubar, mo_delay_image_loads,
  723.               (win->delay_image_loads ? XmxSet : XmxNotSet));
  724.   XmxRSetSensitive (win->menubar, mo_expand_images_current,
  725.             win->delay_image_loads ? XmxSensitive : XmxNotSensitive);
  726.  
  727.   XmxRSetSensitive (win->menubar, mo_annotate, XmxSensitive);
  728.   XmxRSetSensitive (win->menubar, mo_annotate_edit, XmxNotSensitive);
  729.   XmxRSetSensitive (win->menubar, mo_annotate_delete, XmxNotSensitive);
  730.  
  731. #ifdef HAVE_AUDIO_ANNOTATIONS
  732.   /* If we're not audio capable, don't provide the menubar entry. */
  733.   if (!mo_audio_capable ())
  734.     XmxRSetSensitive (win->menubar, mo_audio_annotate, XmxNotSensitive);
  735. #endif
  736.  
  737. #ifdef HAVE_DTM
  738.   mo_set_dtm_menubar_functions (win);
  739. #endif
  740.  
  741.   title_label = XmxMakeLabel (form, "Document Title:");
  742.   XmxSetArg (XmNcursorPositionVisible, False);
  743.   XmxSetArg (XmNeditable, False);
  744.   win->title_text = XmxMakeTextField (form);
  745.  
  746.   url_label = XmxMakeLabel (form, "Document URL:");
  747.   XmxSetArg (XmNcursorPositionVisible, False);
  748.   XmxSetArg (XmNeditable, False);
  749.   win->url_text = XmxMakeTextField (form);
  750.  
  751.   win->logo = XmxMakeNamedPushButton (form, NULL, "logo", icon_pressed_cb, NULL);
  752.  
  753.   if (Rdata.larry_bitmaps)
  754.     {
  755.       xmosaic_right_pix = XmxCreatePixmapFromBitmap
  756.     (win->logo, xmosaic_larry_right_bits, xmosaic_larry_right_width,
  757.      xmosaic_larry_right_height);
  758.       xmosaic_left_pix = XmxCreatePixmapFromBitmap
  759.     (win->logo, xmosaic_larry_left_bits, xmosaic_larry_left_width,
  760.      xmosaic_larry_left_height);
  761.       xmosaic_up_pix = XmxCreatePixmapFromBitmap
  762.     (win->logo, xmosaic_larry_bits, xmosaic_larry_width,
  763.      xmosaic_larry_height);
  764.       xmosaic_down_pix = XmxCreatePixmapFromBitmap
  765.     (win->logo, xmosaic_larry_down_bits, xmosaic_larry_down_width,
  766.      xmosaic_larry_down_height);
  767.     }
  768.   else
  769.     {
  770.       xmosaic_right_pix = XmxCreatePixmapFromBitmap
  771.     (win->logo, xmosaic_right_bits, xmosaic_right_width,
  772.      xmosaic_right_height);
  773.       xmosaic_left_pix = XmxCreatePixmapFromBitmap
  774.     (win->logo, xmosaic_left_bits, xmosaic_left_width,
  775.      xmosaic_left_height);
  776.       xmosaic_up_pix = XmxCreatePixmapFromBitmap
  777.     (win->logo, xmosaic_bits, xmosaic_width,
  778.      xmosaic_height);
  779.       xmosaic_down_pix = XmxCreatePixmapFromBitmap
  780.     (win->logo, xmosaic_down_bits, xmosaic_down_width,
  781.      xmosaic_down_height);
  782.     }
  783.  
  784.   if (IconsMade)
  785.     {
  786.        XmxApplyPixmapToLabelWidget
  787.         (win->logo, IconPix[0]);
  788.     }
  789.   else
  790.     {
  791.        XmxApplyPixmapToLabelWidget
  792.         (win->logo, xmosaic_up_pix);
  793.     }
  794.  
  795.   XmxSetArg (WbNtext, NULL);
  796.   win->last_width = 0;
  797.   XmxSetArg (XmNresizePolicy, XmRESIZE_ANY);
  798.   XmxSetArg (WbNpreviouslyVisitedTestFunction, (long)anchor_visited_predicate);
  799.   XmxSetArg (WbNpointerMotionCallback, (long)pointer_motion_callback);
  800.   XmxSetArg (WbNfancySelections, win->pretty ? True : False);
  801.   XmxSetArg (WbNverticalScrollOnRight, True);
  802.   XmxSetArg (WbNdelayImageLoads, win->delay_image_loads ? True : False);
  803.   XmxSetArg (XmNshadowThickness, 2);
  804.   win->scrolled_win = XtCreateWidget ("view", htmlWidgetClass,
  805.                       form, Xmx_wargs, Xmx_n);
  806.   XtManageChild (win->scrolled_win);
  807.   mo_register_image_resolution_function (win);
  808.   XmxAddCallback (win->scrolled_win, WbNanchorCallback, anchor_cb, 0);
  809.   XmxAddCallback (win->scrolled_win, WbNlinkCallback, link_callback, 0);
  810.   XmxAddCallback (win->scrolled_win, WbNsubmitFormCallback,
  811.           submit_form_callback, 0);
  812.  
  813.   Xmx_n = 0;
  814.   XmxSetArg (WbNview, (long)(&win->view));
  815.   XtGetValues (win->scrolled_win, Xmx_wargs, Xmx_n);
  816.  
  817.   XmxAddEventHandler
  818.     (win->view, KeyPressMask, mo_view_keypress_handler, 0);
  819.  
  820.   XmxSetArg (XmNresizePolicy, XmRESIZE_ANY);
  821.   XmxSetArg (XmNresizable, True);
  822.   win->bottom_form = XmxMakeForm (form);
  823.  
  824.   /* Children of win->bottom_form. */
  825.   {
  826.     if (Rdata.track_pointer_motion)
  827.       {
  828.     XmxSetArg (XmNalignment, XmALIGNMENT_BEGINNING);
  829.     win->tracker_label = XmxMakeLabel (win->bottom_form, " ");
  830.       }
  831.  
  832.     XmxSetArg (XmNmarginWidth, 0);
  833.     XmxSetArg (XmNmarginHeight, 0);
  834.     XmxSetArg (XmNpacking, XmPACK_TIGHT);
  835.     XmxSetArg (XmNresizable, True);
  836.     win->button_rc = XmxMakeHorizontalRowColumn (win->bottom_form);
  837.  
  838.     /* Children of win->button_rc. */
  839.     {
  840.       win->back_button = XmxMakePushButton
  841.     (win->button_rc, "Back", menubar_cb, mo_back);
  842.       win->forward_button = XmxMakePushButton
  843.     (win->button_rc, "Forwd", menubar_cb, mo_forward);
  844.       win->home_button = XmxMakePushButton
  845.     (win->button_rc, "Home", menubar_cb, mo_home_document);
  846.       if (!Rdata.simple_interface)
  847.     win->reload_button = XmxMakePushButton
  848.       (win->button_rc, "Reload", menubar_cb, mo_reload_document);
  849.       if (!Rdata.simple_interface)
  850.     win->open_button = XmxMakePushButton
  851.       (win->button_rc, "Open", menubar_cb, mo_open_document);
  852.       win->save_button = XmxMakePushButton
  853.     (win->button_rc, "Save", menubar_cb, mo_save_document);
  854.       win->tex_button = XmxMakePushButton
  855.     (win->button_rc, "(La)TeX", menubar_cb, mo_tex_document);
  856.       win->clone_button = XmxMakePushButton
  857.     (win->button_rc, "Clone", menubar_cb, mo_clone_window);
  858.       if (!Rdata.simple_interface)
  859.     win->new_button = XmxMakePushButton
  860.       (win->button_rc, "New", menubar_cb, mo_new_window);
  861.       win->close_button = XmxMakePushButton
  862.     (win->button_rc, "Close", menubar_cb, mo_close_window);
  863.     }
  864.  
  865.     if (Rdata.track_pointer_motion)
  866.       {
  867.     XmxSetOffsets (win->tracker_label, 0, 0, 10, 10);
  868.     XmxSetConstraints
  869.       (win->tracker_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM,
  870.        XmATTACH_FORM, NULL, NULL, NULL, NULL);
  871.     XmxSetOffsets (win->button_rc, 2, 5, 10, 10);
  872.     XmxSetConstraints
  873.       (win->button_rc, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
  874.        XmATTACH_FORM, win->tracker_label, NULL, NULL, NULL);
  875.       }
  876.     else
  877.       {
  878.     XmxSetOffsets (win->button_rc, 5, 5, 10, 10);
  879.     XmxSetConstraints
  880.       (win->button_rc, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  881.        XmATTACH_FORM, NULL, NULL, NULL, NULL);
  882.       }
  883.  
  884.   }
  885.  
  886.   /* Constraints for form. */
  887.   XmxSetConstraints
  888.     (win->menubar->base, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM,
  889.      XmATTACH_FORM, NULL, NULL, NULL, NULL);
  890.  
  891.   /* Top to menubar, bottom to nothing,
  892.      left to form, right to nothing. */
  893.   XmxSetOffsets (title_label, 13, 0, 10, 0);
  894.   XmxSetConstraints
  895.     (title_label,
  896.      XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  897.      win->menubar->base, NULL, NULL, NULL);
  898.   /* Top to menubar, bottom to nothing,
  899.      Left to title label, right to logo. */
  900.   XmxSetOffsets (win->title_text, 9, 1, 9, 8);
  901.   XmxSetConstraints
  902.     (win->title_text,
  903.      XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_WIDGET,
  904.      win->menubar->base, NULL, title_label, win->logo);
  905.   /* Top to title text, bottom to nothing,
  906.      left to form, right to nothing. */
  907.   XmxSetOffsets (url_label, 16, 0, 10, 0);
  908.   XmxSetConstraints
  909.     (url_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  910.      win->title_text, NULL, NULL, NULL);
  911.   /* Top to title text, bottom to nothing,
  912.      Left to url label, right to logo. */
  913.   XmxSetOffsets (win->url_text, 12, 1, 8, 8);
  914.   XmxSetConstraints
  915.     (win->url_text,
  916.      XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_WIDGET,
  917.      win->title_text, NULL, url_label, win->logo);
  918.   /* Top to menubar, bottom to nothing,
  919.      left to nothing, right to form. */
  920.   XmxSetOffsets (win->logo, 8, 0, 0, 7);
  921.   XmxSetConstraints
  922.     (win->logo,
  923.      XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
  924.      win->menubar->base, NULL, NULL, NULL);
  925.  
  926.   /* Top to logo, bottom to bottom form,
  927.      Left to form, right to form. */
  928.   XmxSetOffsets (win->scrolled_win, 7, 2, 7, 7);
  929.   XmxSetConstraints
  930.     (win->scrolled_win,
  931.      XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
  932.      win->logo, win->bottom_form, NULL, NULL);
  933.  
  934.   XmxSetOffsets (win->bottom_form, 10, 2, 2, 2);
  935.   XmxSetConstraints
  936.     (win->bottom_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
  937.      XmATTACH_FORM, NULL, NULL, NULL, NULL);
  938.  
  939.   /* Can't go back or forward if we haven't gone anywhere yet... */
  940.   mo_back_impossible (win);
  941.   mo_forward_impossible (win);
  942.  
  943.   return;
  944. }
  945. #endif
  946.  
  947. #ifndef _AMIGA
  948. /****************************************************************************
  949.  * name:    mo_delete_window
  950.  * purpose: Shut down a window.
  951.  * inputs:
  952.  *   - mo_window *win: The window.
  953.  * returns:
  954.  *   mo_succeed
  955.  * remarks:
  956.  *   This can be called, among other places, from the WM_DELETE_WINDOW
  957.  *   handler.  By the time we get here, we must assume the window is already
  958.  *   in the middle of being shut down.
  959.  *   We must explicitly close every dialog that be open as a child of
  960.  *   the window, because window managers too stupid to do that themselves
  961.  *   will otherwise allow them to stay up.
  962.  ****************************************************************************/
  963. #define POPDOWN(x) \
  964.   if (win->x) XtUnmanageChild (win->x)
  965.  
  966. mo_status mo_delete_window (mo_window *win)
  967. {
  968.   mo_node *node;
  969.  
  970.   if (!win)
  971.     return mo_fail;
  972.  
  973.   node = win->history;
  974.  
  975.   POPDOWN (source_win);
  976.   POPDOWN (save_win);
  977.   POPDOWN (savebinary_win);
  978.   POPDOWN (open_win);
  979.   POPDOWN (mail_win);
  980.   POPDOWN (mailhot_win);
  981.   POPDOWN (edithot_win);
  982.   POPDOWN (mailhist_win);
  983.   POPDOWN (print_win);
  984.   POPDOWN (history_win);
  985.   POPDOWN (open_local_win);
  986.   POPDOWN (hotlist_win);
  987.   POPDOWN (whine_win);
  988.   POPDOWN (annotate_win);
  989.   POPDOWN (search_win);
  990.   POPDOWN (searchindex_win);
  991. #ifdef HAVE_DTM
  992.   POPDOWN (dtmout_win);
  993. #endif
  994. #ifdef HAVE_AUDIO_ANNOTATIONS
  995.   POPDOWN (audio_annotate_win);
  996. #endif
  997.   XtPopdown (win->base);
  998.  
  999.   /* Free up some of the HTML Widget's state */
  1000.   HTMLFreeImageInfo (win->scrolled_win);
  1001.  
  1002.   while (node)
  1003.     {
  1004.       mo_node *tofree = node;
  1005.       node = node->next;
  1006.       mo_free_node_data (tofree);
  1007.       free (tofree);
  1008.     }
  1009.  
  1010.   free (win->search_start);
  1011.   free (win->search_end);
  1012.  
  1013.   /* This will free the win structure (but none of its elements
  1014.      individually) and exit if this is the last window in the list. */
  1015.   mo_remove_window_from_list (win);
  1016.  
  1017.   /* Go get another current_win. */
  1018.   mo_set_current_cached_win (mo_next_window (NULL));
  1019.  
  1020.   return mo_succeed;
  1021. }
  1022. #endif
  1023.  
  1024.  
  1025. #ifndef _AMIGA
  1026. /****************************************************************************
  1027.  * name:    mo_open_window_internal (PRIVATE)
  1028.  * purpose: Make a mo_window struct and fill up the GUI.
  1029.  * inputs:
  1030.  *   - Widget        base: The dialog widget on which this window is
  1031.  *              to be based.
  1032.  *   - mo_window *parent: The parent mo_window struct for this window,
  1033.  *              if one exists; this can be NULL.
  1034.  * returns:
  1035.  *   The new window (mo_window *).
  1036.  * remarks:
  1037.  *   This routine must set to 0 all elements in the mo_window struct
  1038.  *   that can be tested by various routines to see if various things
  1039.  *   have been done yet (popup windows created, etc.).
  1040.  ****************************************************************************/
  1041. static mo_window *mo_open_window_internal (Widget base, mo_window *parent)
  1042. {
  1043.   mo_window *win;
  1044.  
  1045.   win = (mo_window *)malloc (sizeof (mo_window));
  1046.   win->id = XmxMakeNewUniqid ();
  1047.   XmxSetUniqid (win->id);
  1048.  
  1049.   win->base = base;
  1050.  
  1051.   win->source_win = 0;
  1052.   win->save_win = 0;
  1053.   win->savebinary_win = 0;
  1054.   win->open_win = win->open_text = win->open_local_win = 0;
  1055.   win->mail_win = win->mailhot_win = win->edithot_win = win->mailhist_win = 0;
  1056.   win->print_win = 0;
  1057.   win->history_win = win->history_list = 0;
  1058.   win->hotlist_win = win->hotlist_list = 0;
  1059.   win->whine_win = win->whine_text = 0;
  1060.   win->annotate_win = 0;
  1061.   win->search_win = win->search_win_text = 0;
  1062.   win->searchindex_win = win->searchindex_win_label = win->searchindex_win_text = 0;
  1063. #ifdef HAVE_DTM
  1064.   win->dtmout_win = win->dtmout_text = 0;
  1065. #endif
  1066. #ifdef HAVE_AUDIO_ANNOTATIONS
  1067.   win->audio_annotate_win = 0;
  1068. #endif
  1069.  
  1070.   win->history = NULL;
  1071.   win->current_node = 0;
  1072.   win->reloading = 0;
  1073.   win->source_text = 0;
  1074.   win->format_optmenu = 0;
  1075.   win->save_format = 0;
  1076.   if (!parent)
  1077.     win->font_size = mo_regular_fonts;
  1078.   else
  1079.     win->font_size = parent->font_size;
  1080.  
  1081.   win->underlines_snarfed = 0;
  1082.   if (!parent)
  1083.     win->underlines_state = mo_default_underlines;
  1084.   else
  1085.     win->underlines_state = parent->underlines_state;
  1086.  
  1087.   win->pretty = Rdata.default_fancy_selections;
  1088.  
  1089.   win->mail_format = 0;
  1090.  
  1091. #ifdef HAVE_AUDIO_ANNOTATIONS
  1092.   win->record_fnam = 0;
  1093.   win->record_pid = 0;
  1094. #endif
  1095.  
  1096.   win->print_text = 0;
  1097.   win->print_format = 0;
  1098.  
  1099.   win->target_anchor = 0;
  1100.   /* Create search_start and search_end. */
  1101.   win->search_start = (void *)malloc (sizeof (ElementRef));
  1102.   win->search_end = (void *)malloc (sizeof (ElementRef));
  1103.  
  1104. #ifdef ISINDEX
  1105.   /* We don't know yet. */
  1106.   win->keyword_search_possible = -1;
  1107. #endif
  1108.  
  1109.   /* Install all the GUI bits & pieces. */
  1110.   mo_fill_window (win);
  1111.  
  1112.   /* Register win with internal window list. */
  1113.   mo_add_window_to_list (win);
  1114.  
  1115.   /* Pop the window up. */
  1116.   XtPopup (win->base, XtGrabNone);
  1117.   XFlush (dsp);
  1118.   XSync (dsp, False);
  1119.  
  1120.   if ((!IconsMade)&&(!Rdata.larry_bitmaps))
  1121.     {
  1122.       MakeAnimationPixmaps(win->logo);
  1123.       IconsMade = 1;
  1124.       XmxApplyPixmapToLabelWidget
  1125.         (win->logo, IconPix[0]);
  1126.       logo_count = 0;
  1127.     }
  1128.  
  1129.   /* Set the font size. */
  1130.   if (win->font_size != mo_regular_fonts)
  1131.     mo_set_fonts (win, win->font_size);
  1132.  
  1133.   /* Set the underline state. */
  1134.   mo_set_underlines (win, win->underlines_state);
  1135.  
  1136.   /* Set the fancy selections toggle to the starting value. */
  1137.   mo_set_fancy_selections_toggle (win);
  1138.  
  1139.   return win;
  1140. }
  1141. #endif
  1142.  
  1143.  
  1144. #ifndef _AMIGA
  1145. /****************************************************************************
  1146.  * name:    delete_cb (PRIVATE)
  1147.  * purpose: Callback for the WM_DELETE_WINDOW protocol.
  1148.  * inputs:
  1149.  *   - as per XmxCallback
  1150.  * returns:
  1151.  *   nothing
  1152.  * remarks:
  1153.  *   By the time we get called here, the window has already been popped
  1154.  *   down.  Just call mo_delete_window to clean up.
  1155.  ****************************************************************************/
  1156. static XmxCallback (delete_cb)
  1157. {
  1158.   mo_window *win = (mo_window *)client_data;
  1159.   mo_delete_window (win);
  1160.   return;
  1161. }
  1162. #endif
  1163.  
  1164.  
  1165. #ifndef _AMIGA
  1166. /****************************************************************************
  1167.  * name:    mo_make_window (PRIVATE)
  1168.  * purpose: Make a new window from scratch.
  1169.  * inputs:
  1170.  *   - Widget       parent: Parent for the new window shell.
  1171.  *   - mo_window *parentw: Parent window, if one exists (may be NULL).
  1172.  * returns:
  1173.  *   The new window (mo_window *).
  1174.  * remarks:
  1175.  *   The 'parent window' parentw is the window being cloned, or the
  1176.  *   window in which the 'new window' command was triggered, etc.
  1177.  *   Some GUI properties are inherited from it, if it exists (fonts,
  1178.  *   anchor appearance, etc.).
  1179.  ****************************************************************************/
  1180. static mo_window *mo_make_window (Widget parent, mo_window *parentw)
  1181. {
  1182.   Widget base;
  1183.   mo_window *win;
  1184.   Atom WM_DELETE_WINDOW;
  1185.  
  1186.   XmxSetArg (XmNtitle, (long)"NCSA Mosaic: Document View");
  1187.   XmxSetArg (XmNiconName, (long)"Mosaic");
  1188.   XmxSetArg (XmNallowShellResize, False);
  1189.   base = XtCreatePopupShell ("shell", topLevelShellWidgetClass,
  1190.                  toplevel, Xmx_wargs, Xmx_n);
  1191.   Xmx_n = 0;
  1192.  
  1193. #ifdef EDITRES_SUPPORT
  1194.   XtAddEventHandler(base, (EventMask) 0, TRUE,
  1195.             (XtEventHandler) _XEditResCheckMessages, NULL);
  1196. #endif
  1197.  
  1198.   win = mo_open_window_internal (base, parentw);
  1199.  
  1200.   WM_DELETE_WINDOW = XmInternAtom(dsp, "WM_DELETE_WINDOW", False);
  1201.   XmAddWMProtocolCallback(base, WM_DELETE_WINDOW, delete_cb, (XtPointer)win);
  1202.  
  1203.   return win;
  1204. }
  1205.  
  1206.  
  1207. /****************************************************************************
  1208.  * name:    mo_open_another_window_internal (PRIVATE)
  1209.  * purpose: Open a new window from an existing window.
  1210.  * inputs:
  1211.  *   - mo_window *win: The old window.
  1212.  * returns:
  1213.  *   The new window (mo_window *).
  1214.  * remarks:
  1215.  *   This routine handles (optional) autoplace of new windows.
  1216.  ****************************************************************************/
  1217. static mo_window *mo_open_another_window_internal (mo_window *win)
  1218. {
  1219.   Dimension oldx, oldy;
  1220.   Dimension scrx = WidthOfScreen (XtScreen (win->base));
  1221.   Dimension scry = HeightOfScreen (XtScreen (win->base));
  1222.   Dimension x, y;
  1223.   Dimension width, height;
  1224.   mo_window *newwin;
  1225.  
  1226.   XtVaGetValues (win->base, XmNx, &oldx, XmNy, &oldy,
  1227.          XmNwidth, &width, XmNheight, &height, NULL);
  1228.  
  1229.   /* Ideally we open down and over 40 pixels... is this possible? */
  1230.   x = oldx + 40; y = oldy + 40;
  1231.   /* If not, deal with it... */
  1232.   while (x + width > scrx)
  1233.     x -= 80;
  1234.   while (y + height > scry)
  1235.     y -= 80;
  1236.  
  1237.   XmxSetArg (XmNdefaultPosition, False);
  1238.   if (Rdata.auto_place_windows)
  1239.     {
  1240.       char geom[20];
  1241.       sprintf (geom, "+%d+%d\0", x, y);
  1242.       XmxSetArg (XmNgeometry, (long)geom);
  1243.     }
  1244.   XmxSetArg (XmNwidth, width);
  1245.   XmxSetArg (XmNheight, height);
  1246.  
  1247.   newwin = mo_make_window (toplevel, win);
  1248.   mo_set_current_cached_win (newwin);
  1249.   return newwin;
  1250. }
  1251.  
  1252.  
  1253. /****************************************************************************
  1254.  * name:    mo_open_window
  1255.  * purpose: Open a new window to view a given URL.
  1256.  * inputs:
  1257.  *   - Widget       parent: The parent Widget for the new window's shell.
  1258.  *   - char         *url: The URL to view in the new window.
  1259.  *   - mo_window *parentw: The (optional) parent window of the new window.
  1260.  * returns:
  1261.  *   The new window.
  1262.  * remarks:
  1263.  *
  1264.  ****************************************************************************/
  1265. mo_window *mo_open_window (Widget parent, char *url, mo_window *parentw)
  1266. {
  1267.   mo_window *win;
  1268.  
  1269.   win = mo_make_window (parent, parentw);
  1270.  
  1271.   mo_set_current_cached_win (win);
  1272.  
  1273.   mo_load_window_text (win, url, NULL);
  1274.  
  1275.   return win;
  1276. }
  1277.  
  1278.  
  1279. /****************************************************************************
  1280.  * name:    mo_duplicate_window
  1281.  * purpose: Clone a existing window as intelligently as possible.
  1282.  * inputs:
  1283.  *   - mo_window *win: The existing window.
  1284.  * returns:
  1285.  *   The new window.
  1286.  * remarks:
  1287.  *
  1288.  ****************************************************************************/
  1289. mo_window *mo_duplicate_window (mo_window *win)
  1290. {
  1291.   mo_window *neww = mo_open_another_window_internal (win);
  1292.  
  1293.   mo_duplicate_window_text (win, neww);
  1294.  
  1295.   return neww;
  1296. }
  1297.  
  1298.  
  1299.  
  1300. /****************************************************************************
  1301.  * name:    mo_open_another_window
  1302.  * purpose: Open another window to view a given URL, unless the URL
  1303.  *        indicates that it's pointless to do so
  1304.  * inputs:
  1305.  *   - mo_window      *win: The existing window.
  1306.  *   - char          *url: The URL to view in the new window.
  1307.  *   - char          *ref: The reference (hyperlink text contents) for this
  1308.  *                URL; can be NULL.
  1309.  *   - char *target_anchor: The target anchor to view open opening the
  1310.  *                window, if any.
  1311.  * returns:
  1312.  *   The new window.
  1313.  * remarks:
  1314.  *
  1315.  ****************************************************************************/
  1316. mo_window *mo_open_another_window (mo_window *win, char *url, char *ref,
  1317.                    char *target_anchor)
  1318. {
  1319.   mo_window *neww;
  1320.  
  1321.   /* Check for reference to telnet.  Never open another window
  1322.      if reference to telnet exists; instead, call mo_load_window_text,
  1323.      which knows how to manage current window's access to telnet. */
  1324.   if (!strncmp (url, "telnet:", 7) || !strncmp (url, "tn3270:", 7) ||
  1325.       !strncmp (url, "rlogin:", 7))
  1326.     {
  1327.       mo_load_window_text (win, url, NULL);
  1328.       return NULL;
  1329.     }
  1330.  
  1331.   mo_busy ();
  1332.  
  1333.   neww = mo_open_another_window_internal (win);
  1334.   /* Set it here; hope it gets handled in mo_load_window_text_first
  1335.      (it probably won't, now. */
  1336.   neww->target_anchor = target_anchor;
  1337.   mo_load_window_text (neww, url, ref);
  1338.  
  1339.   return neww;
  1340. }
  1341. #endif /* not amiga */
  1342.  
  1343.  
  1344. /* ------------------------------------------------------------------------ */
  1345.  
  1346. char **gargv;
  1347. int gargc;
  1348.  
  1349. /****************************************************************************
  1350.  * name:    fire_er_up (PRIVATE)
  1351.  * purpose: Callback from timer that actually starts up the application,
  1352.  *        i.e., opens the first window.
  1353.  * inputs:
  1354.  *   - as per XmxCallback
  1355.  * returns:
  1356.  *   Nothing.
  1357.  * remarks:
  1358.  *   This routine figures out what the home document should be
  1359.  *   and then calls mo_open_window().
  1360.  ****************************************************************************/
  1361. void fire_er_up(int gargc, char **gargv)
  1362. {
  1363.   char *home_opt;
  1364.   mo_window *win;
  1365.  
  1366.   /* Pick up default or overridden value out of X resources. */
  1367.   home_document = Rdata.home_document;
  1368.  
  1369.   /* Value of environment variable WWW_HOME overrides that. */
  1370.   if ((home_opt = getenv ("WWW_HOME")) != NULL)
  1371.     home_document = home_opt;
  1372.  
  1373.   /* Value of argv[1], if it exists, sets startup_document.
  1374.      (All other command-line flags will have been picked up by
  1375.      the X resource mechanism.) */
  1376.   if (gargc > 1 && gargv[1] && *gargv[1])
  1377.     startup_document = gargv[1];
  1378.  
  1379.   /* Check for proper home document URL construction. */
  1380.   if (!strstr (home_document, ":"))
  1381.     home_document = mo_url_canonicalize_local (home_document);
  1382.   if (startup_document && !strstr (startup_document, ":"))
  1383.     startup_document = mo_url_canonicalize_local (startup_document);
  1384.  
  1385. //  win = mo_open_window
  1386. //    (toplevel, startup_document ? startup_document : home_document, NULL);
  1387.  
  1388.   return;
  1389. }
  1390.  
  1391.  
  1392. #ifndef _AMIGA
  1393. /****************************************************************************
  1394.  * name:    mo_open_initial_window
  1395.  * purpose: This routine is called when we know we want to open the
  1396.  *        initial Document View window.
  1397.  * inputs:
  1398.  *   none
  1399.  * returns:
  1400.  *   mo_succeed
  1401.  * remarks: This routine is simply a stub that sets a timeout that
  1402.  *        calls fire_er_up() after 10 milliseconds, which does the
  1403.  *        actual work.
  1404.  ****************************************************************************/
  1405. mo_status mo_open_initial_window (void)
  1406. {
  1407.   /* Set a timer that will actually cause the window to open. */
  1408.   XtAppAddTimeOut (app_context, 10,
  1409.            (XtTimerCallbackProc)fire_er_up, (XtPointer)True);
  1410.  
  1411.   return mo_succeed;
  1412. }
  1413.  
  1414.  
  1415. /****************************************************************************
  1416.  * name:    mo_error_handler (PRIVATE)
  1417.  * purpose: Handle X errors.
  1418.  * inputs:
  1419.  *   - Display         *dsp: The X display.
  1420.  *   - XErrorEvent *event: The error event to handle.
  1421.  * returns:
  1422.  *   0, if it doesn't force an exit.
  1423.  * remarks:
  1424.  *   The main reason for this handler is to keep the application
  1425.  *   from crashing on BadAccess errors during calls to XFreeColors().
  1426.  ****************************************************************************/
  1427. static int mo_error_handler (Display *dsp, XErrorEvent *event)
  1428. {
  1429.   char buf[128];
  1430.  
  1431.   XUngrabPointer (dsp, CurrentTime);   /* in case error occurred in Grab */
  1432.  
  1433.   /* BadAlloc errors (on a XCreatePixmap() call)
  1434.      and BadAccess errors on XFreeColors are 'ignoreable' errors */
  1435.   if (event->error_code == BadAlloc ||
  1436.       (event->error_code == BadAccess && event->request_code == 88))
  1437.     return 0;
  1438.   else
  1439.     {
  1440.       /* All other errors are 'fatal'. */
  1441.       XGetErrorText (dsp, event->error_code, buf, 128);
  1442.       fprintf (stderr, "X Error: %s\n", buf);
  1443.       fprintf (stderr, "  Major Opcode:  %d\n", event->request_code);
  1444.  
  1445.       /* Try to close down gracefully. */
  1446.       mo_exit ();
  1447.     }
  1448. }
  1449. #endif
  1450.  
  1451.  
  1452. /****************************************************************************
  1453.  * name:    mo_do_gui
  1454.  * purpose: This is basically the real main routine of the application.
  1455.  * inputs:
  1456.  *   - int    argc: Number of arguments.
  1457.  *   - char **argv: The argument vector.
  1458.  * returns:
  1459.  *   nothing
  1460.  * remarks:
  1461.  *
  1462.  ****************************************************************************/
  1463. void mo_do_gui (int argc, char **argv)
  1464. {
  1465.   /* actually some important stuff in here! */
  1466. #ifndef _AMIGA
  1467.   int use_color = 1;
  1468.   int no_defaults = 0;
  1469.  
  1470.   int i;
  1471.  
  1472.   /* Loop through the args before passing them off to
  1473.      XtAppInitialize() in case we need to catch something first. */
  1474.   for (i = 1; i < argc; i++)
  1475.     {
  1476.       if (!strcmp (argv[i], "-mono"))
  1477.     use_color = 0;
  1478.       if (!strcmp (argv[i], "-color"))
  1479.     use_color = 1;
  1480.       if (!strcmp (argv[i], "-nd"))
  1481.     no_defaults = 1;
  1482.     }
  1483.  
  1484.   /* Motif setup. */
  1485.   XmxStartup ();
  1486.   XmxSetArg (XmNmappedWhenManaged, False);
  1487.   if (no_defaults)
  1488.     {
  1489.       toplevel = XtAppInitialize
  1490.     (&app_context, "Mosaic", options, XtNumber (options),
  1491.      &argc, argv, NULL, Xmx_wargs, Xmx_n);
  1492.     }
  1493.   else
  1494.     {
  1495.       if (use_color)
  1496.     {
  1497.       toplevel = XtAppInitialize
  1498.         (&app_context, "Mosaic", options, XtNumber (options),
  1499.          &argc, argv, color_resources, Xmx_wargs, Xmx_n);
  1500.     }
  1501.       else
  1502.     {
  1503.       toplevel = XtAppInitialize
  1504.         (&app_context, "Mosaic", options, XtNumber (options),
  1505.          &argc, argv, mono_resources, Xmx_wargs, Xmx_n);
  1506.     }
  1507.     }
  1508.  
  1509.   /* Needed for picread.c, right now. */
  1510.   dsp = XtDisplay (toplevel);
  1511.   {
  1512.     XVisualInfo vinfo, *vptr;
  1513.     int cnt;
  1514.  
  1515.     vinfo.visualid =
  1516.       XVisualIDFromVisual
  1517.     (DefaultVisual (dsp,
  1518.             DefaultScreen (dsp)));
  1519.     vptr = XGetVisualInfo (dsp, VisualIDMask, &vinfo, &cnt);
  1520.     Vclass = vptr->class;
  1521.     XFree((char *)vptr);
  1522.   }
  1523.  
  1524.   XtVaGetApplicationResources (toplevel, (XtPointer)&Rdata, resources,
  1525.                    XtNumber (resources), NULL);
  1526.  
  1527.   XSetErrorHandler (mo_error_handler);
  1528.  
  1529.   /* Kill group annotation capability with libwww2 -- IT DOES NOT WORK,
  1530.      so don't even try to change this... */
  1531.   Rdata.annotation_server = NULL;
  1532.  
  1533. #ifdef __sgi
  1534.   /* Turn on debugging malloc if necessary. */
  1535.   if (Rdata.debugging_malloc)
  1536.     mallopt (M_DEBUG, 1);
  1537. #endif
  1538.  
  1539.   global_xterm_str = Rdata.xterm_command;
  1540.  
  1541.   uncompress_program = Rdata.uncompress_command;
  1542.   gunzip_program = Rdata.gunzip_command;
  1543.  
  1544.   tweak_gopher_types = Rdata.tweak_gopher_types;
  1545.   max_wais_responses = Rdata.max_wais_responses;
  1546.  
  1547.   use_default_extension_map = Rdata.use_default_extension_map;
  1548.   global_extension_map = Rdata.global_extension_map;
  1549.   if (Rdata.personal_extension_map)
  1550.     {
  1551.       char *home = getenv ("HOME");
  1552.  
  1553.       if (!home)
  1554.     home = "/tmp";
  1555.  
  1556.       personal_extension_map = (char *)malloc
  1557.     (strlen (home) + strlen (Rdata.personal_extension_map) + 8);
  1558.       sprintf (personal_extension_map, "%s/%s\0", home,
  1559.            Rdata.personal_extension_map);
  1560.     }
  1561.   else
  1562.     personal_extension_map = "\0";
  1563.  
  1564.   use_default_type_map = Rdata.use_default_type_map;
  1565.   global_type_map = Rdata.global_type_map;
  1566.   if (Rdata.personal_type_map)
  1567.     {
  1568.       char *home = getenv ("HOME");
  1569.  
  1570.       if (!home)
  1571.     home = "/tmp";
  1572.  
  1573.       personal_type_map = (char *)malloc
  1574.     (strlen (home) + strlen (Rdata.personal_type_map) + 8);
  1575.       sprintf (personal_type_map, "%s/%s\0", home,
  1576.            Rdata.personal_type_map);
  1577.     }
  1578.   else
  1579.     personal_type_map = "\0";
  1580.  
  1581. #ifdef HAVE_HDF
  1582.   have_hdf = 1;
  1583. #else
  1584.   have_hdf = 0;
  1585. #endif
  1586.  
  1587.   twirl_increment = Rdata.twirl_increment;
  1588.  
  1589.   /* First get the hostname. */
  1590.   machine = (char *)malloc (sizeof (char) * 64);
  1591.   gethostname (machine, 64);
  1592.  
  1593.   /* Then make a copy of the hostname for shortmachine.
  1594.      Don't even ask. */
  1595.   shortmachine = strdup (machine);
  1596.  
  1597.   /* Then find out the full name, if possible. */
  1598.   if (Rdata.full_hostname)
  1599.     {
  1600.       free (machine);
  1601.       machine = Rdata.full_hostname;
  1602.     }
  1603.   else if (!Rdata.gethostbyname_is_evil)
  1604.     {
  1605.       struct hostent *phe;
  1606.  
  1607.       phe = gethostbyname (machine);
  1608.       if (phe && phe->h_name)
  1609.     {
  1610.       free (machine);
  1611.       machine = strdup (phe->h_name);
  1612.     }
  1613.     }
  1614.   /* (Otherwise machine just remains whatever gethostname returned.) */
  1615.  
  1616.   machine_with_domain = (strlen (machine) > strlen (shortmachine) ?
  1617.              machine : shortmachine);
  1618.  
  1619.   /* If there's no tmp directory assigned by the X resource, then
  1620.      look at TMPDIR. */
  1621.   if (!Rdata.tmp_directory)
  1622.     {
  1623.       Rdata.tmp_directory = getenv ("TMPDIR");
  1624.       /* It can still be NULL when we leave here -- then we'll just
  1625.      let tmpnam() do what it does best. */
  1626.     }
  1627.  
  1628.   /* If there's no docs directory assigned by the X resource,
  1629.      then look at MOSAIC_DOCS_DIRECTORY environment variable
  1630.      and then at hardcoded default. */
  1631.   if (!Rdata.docs_directory)
  1632.     {
  1633.       Rdata.docs_directory = getenv ("MOSAIC_DOCS_DIRECTORY");
  1634.       if (!Rdata.docs_directory)
  1635.     Rdata.docs_directory = DOCS_DIRECTORY_DEFAULT;
  1636.       if (!Rdata.docs_directory || !*(Rdata.docs_directory))
  1637.     {
  1638.       fprintf (stderr, "fatal error: nonexistent docs directory\n");
  1639.       exit (-1);
  1640.     }
  1641.     }
  1642.  
  1643.   mo_setup_default_hotlist ();
  1644.   if (Rdata.use_global_history)
  1645.     mo_setup_global_history ();
  1646.   else
  1647.     mo_init_global_history ();
  1648.   mo_setup_pan_list ();
  1649.  
  1650.   /* Write pid into "~/.mosaicpid". */
  1651.   {
  1652.     char *home = getenv ("HOME"), *fnam;
  1653.     FILE *fp;
  1654.  
  1655.     if (!home)
  1656.       home = "/tmp";
  1657.  
  1658.     fnam = (char *)malloc (strlen (home) + 32);
  1659.     sprintf (fnam, "%s/.mosaicpid", home);
  1660.  
  1661.     fp = fopen (fnam, "w");
  1662.     if (fp)
  1663.       {
  1664.     fprintf (fp, "%d\n", getpid());
  1665.     fclose (fp);
  1666.       }
  1667.  
  1668.     free (fnam);
  1669.   }
  1670.  
  1671.   {
  1672.     Widget foo = XmxMakeForm (toplevel);
  1673.     XmString xmstr = XmxMakeXmstrFromString ("NCSA Mosaic");
  1674.     XmxSetArg (XmNlabelString, (long)xmstr);
  1675.     Xmx_w = XtCreateManagedWidget ("blargh", xmLabelGadgetClass,
  1676.                    foo, Xmx_wargs, Xmx_n);
  1677.     XmStringFree (xmstr);
  1678.     Xmx_n = 0;
  1679.   }
  1680.  
  1681.   busy_cursor = XCreateFontCursor (dsp, XC_watch);
  1682.  
  1683.   XtRealizeWidget (toplevel);
  1684.  
  1685.   gargv = argv;
  1686.   gargc = argc;
  1687.  
  1688. #ifndef VMS
  1689.   signal (SIGUSR1, ProcessExternalDirective);
  1690. #endif
  1691.  
  1692.   defer_initial_window = 0;
  1693.  
  1694.   if (!defer_initial_window)
  1695.     mo_open_initial_window ();
  1696.  
  1697.   XtAppMainLoop (app_context);
  1698. #endif /* not amiga */
  1699. }
  1700.  
  1701.  
  1702. /* stuff about external directives left out... */
  1703.  
  1704. long atorgb(char *s)
  1705. {
  1706.     long r,g,b;
  1707.     sscanf(s,"%d/%d/%d\n",&r,&g,&b);
  1708.     return (r<<16)+(g<<8)+b;
  1709. }
  1710.  
  1711. /* MDF 6-10-94
  1712.    The global Rdata structure contains all Mosaic-wide preferences.
  1713.    We first set all fields with our built-in defaults, then see if the
  1714.    user has any prefs files which should override these.
  1715. */
  1716.  
  1717. char *amiga_editor;    /* not in Rdata, because needed by libwww2 */
  1718. char *amiga_sendmail;    /* not in Rdata, because needed by libwww2 */
  1719. char *amiga_telnet;    /* not in Rdata, because needed by libwww2 */
  1720. char *amiga_rlogin;    /* not in Rdata, because needed by libwww2 */
  1721.  
  1722. void amiga_load_prefs(void)
  1723. {
  1724.   FILE *fp;
  1725.   char *s, *p;
  1726.   char line[1004], param[100], *value ;
  1727.   void RexxMenu(int, char *) ;
  1728.  
  1729.   Rdata.use_global_history = TRUE;
  1730.   Rdata.track_visited_anchors = TRUE;
  1731.   Rdata.font = "times/13";
  1732.   Rdata.boldfont = "times/13/bold";
  1733.   Rdata.italicfont = "times/13/italic";
  1734.   Rdata.h1font = "times/24";
  1735.   Rdata.h2font = "times/18";
  1736.   Rdata.h3font = "times/15";
  1737.   Rdata.h4font = "times/13";
  1738.   Rdata.h5font = "times/11";
  1739.   Rdata.h6font = "times/11";
  1740.   Rdata.fixedfont = "courier/13";
  1741.   Rdata.addressfont = "times/13/italic";
  1742.   Rdata.listingfont = "courier/11";
  1743.   Rdata.plainfont = "courier/11";
  1744.   Rdata.home_document = "http://www.omnipresence.com/amosaic/2.0/";
  1745.   Rdata.use_global_history = True;
  1746.   Rdata.display_urls_not_titles = False;
  1747.   Rdata.global_history_file = "s:mosaic-global-history";
  1748.   Rdata.default_hotlist_file = "s:mosaic-hotlist-default";
  1749.   Rdata.tmp_directory = "T:";
  1750.   Rdata.track_pointer_motion = True;
  1751.   Rdata.track_full_url_names = True;
  1752.   Rdata.reload_reloads_images = False;
  1753.   Rdata.delay_image_loads = True;
  1754.   Rdata.use_default_extension_map = True;
  1755.   Rdata.twirling_transfer_icon = True;
  1756.   Rdata.image_cache_size = 400;
  1757.     Rdata.isindex_to_form=TRUE;
  1758.     Rdata.image_buttons=2;
  1759.     Rdata.title_to_window=FALSE;
  1760.     Rdata.u_anchor=0x2020FF;
  1761.     Rdata.f_anchor=0x000080;
  1762.     Rdata.a_anchor=0xCC0000;
  1763.  
  1764.   /* First check the ENV:MOSAIC/PREFS file for prefs information */
  1765.  
  1766.   fp = fopen("env:mosaic/prefs", "r");
  1767.   if (!fp) goto check_env;        /* we have no prefs file. */
  1768.  
  1769.   while (fgets(line, 1000, fp)) {
  1770.  
  1771.     value = stpsym(line, param, 100) ;
  1772.     if (value) value = stpblk(value) ;
  1773.     else continue ;
  1774.     if (*value) value[strlen(value) - 1] = '\0' ;
  1775.  
  1776.     if (stricmp (param, "TempDir") == 0)
  1777.       Rdata.tmp_directory = strdup(value);
  1778.     if (stricmp (param, "Sendmail") == 0)
  1779.       amiga_sendmail = strdup(value);
  1780.     if (stricmp (param, "Editor") == 0)
  1781.       amiga_editor = strdup(value);
  1782.     if (stricmp (param, "Telnet") == 0)
  1783.       amiga_telnet = strdup(value);
  1784.     if (stricmp (param, "Rlogin") == 0)
  1785.       amiga_rlogin = strdup(value);
  1786.  
  1787.     if (!stricmp(param, "ImageCacheSize"))
  1788.       Rdata.image_cache_size = atoi(value);
  1789.     if (!stricmp(param, "DelayImageLoads"))
  1790.       Rdata.delay_image_loads = (stricmp(value, "true"))?0:1;
  1791.     if (!stricmp(param, "TitleToWindow"))
  1792.       Rdata.title_to_window = (stricmp(value, "true"))?0:1;
  1793.     if (!stricmp(param, "IsindexToForm"))
  1794.       Rdata.isindex_to_form = (stricmp(value, "true"))?0:1;
  1795.     if (!stricmp(param, "Buttons")){
  1796.     if(!strnicmp(value, "text",5)) Rdata.image_buttons = 0;
  1797.         else if(!strnicmp(value, "images",7)) Rdata.image_buttons = 1;
  1798.         else if(!strnicmp(value, "images&text",11)) Rdata.image_buttons = 2;
  1799.         }
  1800.  
  1801.     if (!stricmp(param, "Anchor"))
  1802.       Rdata.u_anchor = atorgb(value);
  1803.     if (!stricmp(param, "FollowedAnchor"))
  1804.       Rdata.f_anchor = atorgb(value);
  1805.     if (!stricmp(param, "ActiveAnchor"))
  1806.       Rdata.a_anchor = atorgb(value);
  1807.  
  1808.     if (!stricmp(param, "HomeDocument"))
  1809.       Rdata.home_document = strdup(value);
  1810.     if (!stricmp(param, "DownloadDir"))
  1811.       Rdata.download_dir = strdup(value);
  1812.     if (!stricmp(param, "AddToHotList"))
  1813.       RexxMenu(mo_add_hot_list, value) ;
  1814.     if (!stricmp(param, "JumpToHotList"))
  1815.       RexxMenu(mo_jump_hot_list, value) ;
  1816.     if (!stricmp(param, "PrintCommand"))
  1817.       RexxMenu(mo_print_document, value) ;
  1818.  
  1819.     if (!stricmp(param, "Font"))
  1820.       Rdata.font = strdup(value);
  1821.     if (!stricmp(param, "italicFont"))
  1822.       Rdata.italicfont = strdup(value);
  1823.     if (!stricmp(param, "boldFont"))
  1824.       Rdata.boldfont = strdup(value);
  1825.     if (!stricmp(param, "h1Font"))
  1826.       Rdata.h1font = strdup(value);
  1827.     if (!stricmp(param, "h2Font"))
  1828.       Rdata.h2font = strdup(value);
  1829.     if (!stricmp(param, "h3Font"))
  1830.       Rdata.h3font = strdup(value);
  1831.     if (!stricmp(param, "h4Font"))
  1832.       Rdata.h4font = strdup(value);
  1833.     if (!stricmp(param, "h5Font"))
  1834.       Rdata.h5font = strdup(value);
  1835.     if (!stricmp(param, "h6Font"))
  1836.       Rdata.h6font = strdup(value);
  1837.     if (!stricmp(param, "fixedFont"))
  1838.       Rdata.fixedfont = strdup(value);
  1839.     if (!stricmp(param, "addressFont"))
  1840.       Rdata.addressfont = strdup(value);
  1841.     if (!stricmp(param, "listingFont"))
  1842.       Rdata.listingfont = strdup(value);
  1843.     if (!stricmp(param, "plainFont"))
  1844.       Rdata.plainfont = strdup(value);
  1845.     if (!stricmp(param, "rexxmacro1"))
  1846.       RexxMenu(mo_macro_1, value) ;
  1847.     if (!stricmp(param, "rexxmacro2"))
  1848.       RexxMenu(mo_macro_2, value) ;
  1849.     if (!stricmp(param, "rexxmacro3"))
  1850.       RexxMenu(mo_macro_3, value) ;
  1851.     if (!stricmp(param, "rexxmacro4"))
  1852.       RexxMenu(mo_macro_4, value) ;
  1853.     if (!stricmp(param, "rexxmacro5"))
  1854.       RexxMenu(mo_macro_5, value) ;
  1855.     if (!stricmp(param, "rexxmacro6"))
  1856.       RexxMenu(mo_macro_6, value) ;
  1857.     if (!stricmp(param, "rexxmacro7"))
  1858.       RexxMenu(mo_macro_7, value) ;
  1859.     if (!stricmp(param, "rexxmacro8"))
  1860.       RexxMenu(mo_macro_8, value) ;
  1861.     if (!stricmp(param, "rexxmacro9"))
  1862.       RexxMenu(mo_macro_9, value) ;
  1863.     if (!stricmp(param, "rexxmacro10"))
  1864.       RexxMenu(mo_macro_10, value) ;
  1865.   }
  1866.   fclose(fp);
  1867.  
  1868. check_env:
  1869.   /* Now check the individual environment variables for overrides. */
  1870.  
  1871.   if (s = getenv ("Mosaic/TempDir"))
  1872.     Rdata.tmp_directory = s;
  1873.   if (strcmp (Rdata.tmp_directory, "T:") == 0)
  1874.     if (s = getenv ("HOME"))
  1875.       Rdata.tmp_directory = s;
  1876.  
  1877.   if (s = getenv ("Mosaic/Sendmail"))
  1878.     amiga_sendmail = s;
  1879.   if (!amiga_sendmail)
  1880.     amiga_sendmail = getenv ("Sendmail");
  1881.  
  1882.   if (s = getenv ("Mosaic/Editor"))
  1883.     amiga_editor = s;
  1884.   if (!amiga_editor)
  1885.     amiga_editor = getenv ("Editor");
  1886.  
  1887.   if (s = getenv ("Mosaic/Telnet"))
  1888.     amiga_telnet = s;
  1889.   if (!amiga_telnet)
  1890.     amiga_telnet = getenv ("Telnet");
  1891.  
  1892.   if (s = getenv ("Mosaic/Rlogin"))
  1893.     amiga_rlogin = s;
  1894.   if (!amiga_telnet)
  1895.     amiga_telnet = getenv ("Rlogin");
  1896.  
  1897.   if (s = getenv("Mosaic/ImageCacheSize"))
  1898.     Rdata.image_cache_size = atoi(s);
  1899.   if (s = getenv("Mosaic/DelayImageLoads"))
  1900.     Rdata.delay_image_loads = (stricmp(s, "true"))?0:1;
  1901.   if (s = getenv("Mosaic/TitleToWindow"))
  1902.     Rdata.title_to_window = (stricmp(s, "true"))?0:1;
  1903.  
  1904.     if (s = getenv("Mosaic/IsindexToForm"))
  1905.         Rdata.isindex_to_form = (stricmp(s, "true"))?0:1;
  1906.     if (s = getenv("Mosaic/Buttons")){
  1907.     if(!strnicmp(s, "text",5)) Rdata.image_buttons = 0;
  1908.         else if(!strnicmp(s, "images",7)) Rdata.image_buttons = 1;
  1909.         else if(!strnicmp(s, "images&text",11)) Rdata.image_buttons = 2;
  1910.         }
  1911.  
  1912.  
  1913.     if (s = getenv("Mosaic/Anchor"))
  1914.         Rdata.u_anchor = atorgb(s);
  1915.     if (s = getenv("Mosaic/FollowedAnchor"))
  1916.         Rdata.f_anchor = atorgb(s);
  1917.     if (s = getenv("Mosaic/ActiveAnchor"))
  1918.         Rdata.a_anchor = atorgb(s);
  1919.  
  1920.   if (s = getenv("Mosaic/HomeDocument"))
  1921.     Rdata.home_document = s;
  1922.   if (s = getenv("Mosaic/DownloadDir"))
  1923.     Rdata.download_dir = s;
  1924.   if (s = getenv("Mosaic/AddToHotList"))
  1925.     RexxMenu(mo_add_hot_list, s) ;
  1926.   if (s = getenv("Mosaic/JumpToHotList"))
  1927.     RexxMenu(mo_jump_hot_list, s) ;
  1928.   if (s = getenv("Mosaic/PrintCommand"))
  1929.     RexxMenu(mo_print_document, s) ;
  1930.  
  1931.   if (s = getenv("Mosaic/Font"))
  1932.       Rdata.font = s;
  1933.   if (s = getenv("Mosaic/italicFont"))
  1934.       Rdata.italicfont = s;
  1935.   if (s = getenv("Mosaic/boldFont"))
  1936.       Rdata.boldfont = s;
  1937.   if (s = getenv("Mosaic/h1Font"))
  1938.       Rdata.h1font = s;
  1939.   if (s = getenv("Mosaic/h2Font"))
  1940.       Rdata.h2font = s;
  1941.   if (s = getenv("Mosaic/h3Font"))
  1942.       Rdata.h3font = s;
  1943.   if (s = getenv("Mosaic/h4Font"))
  1944.       Rdata.h4font = s;
  1945.   if (s = getenv("Mosaic/h5Font"))
  1946.       Rdata.h5font = s;
  1947.   if (s = getenv("Mosaic/h6Font"))
  1948.       Rdata.h6font = s;
  1949.   if (s = getenv("Mosaic/fixedFont"))
  1950.       Rdata.fixedfont = s;
  1951.   if (s = getenv("Mosaic/addressFont"))
  1952.       Rdata.addressfont = s;
  1953.   if (s = getenv("Mosaic/listingFont"))
  1954.       Rdata.listingfont = s;
  1955.   if (s = getenv("Mosaic/plainFont"))
  1956.       Rdata.plainfont = s;
  1957.   if (s = getenv("Mosaic/rexxmacro1"))
  1958.       RexxMenu(mo_macro_1, s) ;
  1959.   if (s = getenv("Mosaic/rexxmacro2"))
  1960.       RexxMenu(mo_macro_2, s) ;
  1961.   if (s = getenv("Mosaic/rexxmacro3"))
  1962.       RexxMenu(mo_macro_3, s) ;
  1963.   if (s = getenv("Mosaic/rexxmacro4"))
  1964.       RexxMenu(mo_macro_4, s) ;
  1965.   if (s = getenv("Mosaic/rexxmacro5"))
  1966.       RexxMenu(mo_macro_5, s) ;
  1967.   if (s = getenv("Mosaic/rexxmacro6"))
  1968.       RexxMenu(mo_macro_6, s) ;
  1969.   if (s = getenv("Mosaic/rexxmacro7"))
  1970.       RexxMenu(mo_macro_7, s) ;
  1971.   if (s = getenv("Mosaic/rexxmacro8"))
  1972.       RexxMenu(mo_macro_8, s) ;
  1973.   if (s = getenv("Mosaic/rexxmacro9"))
  1974.       RexxMenu(mo_macro_9, s) ;
  1975.   if (s = getenv("Mosaic/rexxmacro10"))
  1976.       RexxMenu(mo_macro_10, s) ;
  1977. }
  1978.